<template>
  <div style="height: 100%;">
           <div class="dashboard-container" v-if="shopInfo">
            <div class="flex renrow-box" v-if="isExpress">
              <img src="@/assets/img/home-waring.png" alt="">
              <div>您当前存在即将到期的服务,请<span @click="goRenew">立即续费</span></div>
            </div>
        <div>
          <!-- 网格布局 -->
          <grid-layout :layout.sync="layout"
                 :col-num="24"
                 :margin="[15, 15]"
                 :is-draggable="draggable"
                 :is-resizable="resizable"
                 :auto-size="false"
                 :vertical-compact="true"
                 :use-css-transforms="true"
                 :rowHeight="10"
                 @layout-updated="onLayoutUpdated"
                
    >
             <grid-item v-for="item in layout"
                  class="grid-item"
                  :static="item.static"
                  :isResizable="item.isResizable"
                  :isDraggable="item.isDraggable"
                  :useCssTransforms="item.useCssTransforms"
                  :x="item.x"
                  :y="item.y"
                  :w="item.w"
                  :h="item.h"
                  :minW="item.minW"
                  :minH="item.minH"
                  :i="item.i"
                  :key="item.i"
                  :data-grid-key="item.i"
                  drag-allow-from=".drag-handle"
                  drag-ignore-from=".no-drag"
       >
        <!-- 拖拽手柄固定在左上角 -->
        <div class="drag-handle" v-if="!item.static">
          <div class="drag-icon">⋮⋮</div>
        </div>
          <component v-if="isMounted" :is="item.id" :ref="'comp_' + item.i" @layouts="resetLayout" />
      </grid-item>
    </grid-layout>
   
    
  </div>
           <!-- 工具栏 -->
     <!-- <div v-if="actualTotalHeight != 450" class="dashboard-toolbar"  @click="resetLayout">
         重置布局
     </div> -->
  </div>
  <div v-else-if="checkPermi(['searchTenantID'])" style="font-size:24px">
      <h2>破晓余额： <span style="font-weight:bold;color: blue;">{{poxiaoyue}}</span></h2>
      <!-- <el-button type="primary" @click="testAES">测试加密</el-button> -->
      <el-row :gutter="20">
        <el-col :span="12">
          <el-card class="update-log">
            <div slot="header" class="clearfix">
              <span>商家商品统计</span>
            </div>
            <div class="table_box">
              <el-table @sort-change="goodsTableChange" border stripe :data="supplerGoodsTotal" height="500">
                <el-table-column prop="tenant_name" label="商家名称">
                </el-table-column>
                <el-table-column prop="ziyingCot" label="手动上架" sort-by sortable="custom">
                </el-table-column>
                <el-table-column prop="apiCot" label="API上架" sort-by sortable="custom">
                </el-table-column>
                <el-table-column prop="cot" label="在售总数" sort-by sortable="custom">
                </el-table-column>
              </el-table>
            </div>
          </el-card>
        </el-col>
        <el-col :span="12">
          <el-card class="update-log">
            <div slot="header" class="clearfix">
              <span>商家昨日上新统计</span>
            </div>
            <div class="table_box">
              <!-- <div style="margin:10px 0">
                <el-date-picker style="width:215px" size="small" v-model="timer" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" @change="timerChange">
                </el-date-picker>
              </div> -->
              <el-table @sort-change="goodsYestodayTableChange" border stripe :data="supplerGoodsYesterday" height="500">
                <el-table-column prop="tenant_name" label="商家名称">
                </el-table-column>
                <el-table-column prop="ziyingCot" label="手动上架" sort-by sortable="custom">
                </el-table-column>
                <el-table-column prop="apiCot" label="API上架" sort-by sortable="custom">
                </el-table-column>
                <el-table-column prop="cot" label="上架总数" sort-by sortable="custom">
                </el-table-column>
              </el-table>
            </div>
          </el-card>
        </el-col>

      </el-row>
      <el-row style="margin-top:15px" :gutter="20">
        <el-col :span="12">
          <el-card class="update-log">
            <div slot="header" class="clearfix">
              <span>商家虞豆统计</span>
            </div>
            <div class="table_box">
              <el-table @sort-change="yudouSortChange" border stripe :data="yudouList" height="500">
                <el-table-column prop="tenantName" label="商家名称">
                </el-table-column>
                <el-table-column sort-by sortable="custom" prop="tenantcampNumber" label="当前虞豆"></el-table-column>

                <el-table-column sort-by sortable="custom" prop="sumXHCampNumber" label="总消耗虞豆"></el-table-column>
                <el-table-column sort-by sortable="custom" prop="sumCZCampNumber" label="总充值虞豆"></el-table-column>

              </el-table>
            </div>
          </el-card>
        </el-col>
        <el-col :span="12">
          <el-card class="update-log">
            <div slot="header" class="clearfix">
              <span>商家注册用户统计</span>
            </div>
            <div class="table_box">
              <el-table border stripe :data="supplerUserTotal" height="500">
                <el-table-column prop="tenant_name" label="商家名称">
                </el-table-column>
                <el-table-column prop="cot" label="注册用户">
                </el-table-column>
              </el-table>
            </div>
          </el-card>
        </el-col>

      </el-row>
      <el-row style="margin-top:15px" :gutter="20">
        <el-col :span="12">
          <el-card class="update-log">
            <div slot="header" class="clearfix">
              <span>消费虞豆类型统计</span>
            </div>
            <div class="table_box">
              <el-table @sort-change="yudouTypeTableChange" border stripe :data="moduleYudouList" height="500">
                <el-table-column prop="tenantName" label="虞豆类型">
                  <template slot-scope="scope">
                    <el-tag :type="commonMaps.jifenTypeMap[scope.row.msg_type].type">{{ commonMaps.jifenTypeMap[scope.row.msg_type].label }}</el-tag>
                  </template>
                </el-table-column>
                <el-table-column sort-by sortable="custom" prop="cot" label="变动次数"></el-table-column>
                <el-table-column sort-by sortable="custom" prop="sum" label="虞豆数量"></el-table-column>
                <!-- <el-table-column sort-by sortable="custom" prop="sumCZCampNumber" label="总充值虞豆"></el-table-column> -->
              </el-table>
            </div>
          </el-card>
        </el-col>
        <el-col :span="12">
          <el-card class="update-log">
            <div slot="header" class="clearfix">
              <span>服务包开通统计</span>
            </div>
            <div class="table_box">
              <el-table border stripe :data="serverList" height="500">
                <el-table-column prop="tenantName" label="商家名">
                </el-table-column>
                <el-table-column prop="baseServer" label="基础包">
                  <template slot-scope="scope">
                    <el-tag v-if="scope.row.baseServer==2">开通</el-tag>
                    <el-tag type="info" v-else>未开通</el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="baseExpireTime" label="基础包到期时间">
                  <template slot-scope="scope">
                    <span v-if="scope.row.baseExpireTime">
                      {{ scope.row.baseExpireTime.substr(0,10) }}
                    </span>
                  </template>
                </el-table-column>
                 <el-table-column prop="cot" label="商城包">
                  <template slot-scope="scope">
                    <el-tag v-if="scope.row.shopServer == 2">开通</el-tag>
                    <el-tag type="info" v-else>未开通</el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="shopExpireTime" label="商城包到期时间">
                  <template slot-scope="scope">
                    <span v-if="scope.row.shopExpireTime">
                      {{ scope.row.shopExpireTime.substr(0,10) }}
                    </span>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
    <div v-else style="color:#666;font-size:30px;text-align:center;line-height:300px">
      欢迎使用 虞都互联~
    </div>

    <noticeDetailDialog ref="noticeDetailDialog"></noticeDetailDialog>
    <expireSoonDialog  ref="expireSoonDialog" @closed="onExpireDialogClosed"></expireSoonDialog>
  </div>
</template>

<script>
import homeApi from "@/api/home/newIndex";
// 批量加载所有组件
import {GridLayout, GridItem} from "vue-grid-layout"
import defaultLayout from "./indexComponents/defaultLayout";
import _ from "lodash";
import checkPhoneApi from "@/api/gameConfig/checkPhonePx";
import ComponentLoader from "./indexComponents/asyncLoader";
import noticeDetailDialog from "../components/common/noticeDetailDialog.vue";
import expireSoonDialog from "../components/common/expireSoonDialog.vue";
import {

  goodsCountByTenant,
  yudouCountByTenant,

  getSupplerUserTotal,
  getModuleYudou,
  getServiceCount

} from "@/api/tenantApis/indexStatistics.js";
export default {
  components: {
    GridLayout,
    GridItem,
    noticeDetailDialog,
    expireSoonDialog
  },
  data() {
    return {
      isExpress:false,
      isExpressData:[],
      isMounted: false,
      layout: [],
      draggable: true,
      resizable: true,
      index: 0,
      layoutStorageKey: 'tongji-dashboard-layout',
      actualTotalHeight: 0, // 初始高度为0，等待计算完成后显示按钮


          // 以下是管理端数据
       supplerUserTotal: [],
        supplerGoodsTotal: [],
        supplerGoodsYesterday: [],
      timer: [],
      poxiaoyue: "",
      yudouList:[],
        yudouParams: {
        sortColumn: "",
        sort: "",
      },monitorTaskErrNum: {},
      
      moduleYudouList:[],
       yudouTypeParams: {
        sortColumn: "",
        sort: "",
      },
      serverList:[],
      shangpintongjiCanshu:{
        sortColumn:'cot',
        sort:'desc'
      },
      zuoriShangjiaCanshu:{ 
        day: 1 ,
        sortColumn:'cot',
        sort:'desc'
      }
    }
  },
  computed: {
   userInfo() {
      return this.$store.getters.userInfo;
    },
    shopInfo() {
      return this.$store.getters.shopInfo;
    },
      routeData() {
      return this.$store.state.permission.routeData;
    },
    // 计算网格布局的总高度
    gridTotalHeight() {
      if (!this.layout || this.layout.length === 0) return 0;
      
      // 找到最底部的网格项
      const maxY = Math.max(...this.layout.map(item => item.y + item.h));
      
      // 计算总高度 = 最大Y位置 * rowHeight + 底部边距
      const totalHeight = maxY * 10 + 15; // 10是rowHeight，15是底部margin
      
      return totalHeight;
    }
  },
 watch: {
    userInfo: {
      handler(val) {
        this.getErpVer();
        if (val.tenantId != 1) {
          // 这是商户
          // this.getBZJ();
          // this.getDaiban();
          // this.getGoodsNum();
          // this.getMyBuyNums();
          // this.getMySellNums();
          // this.gethuliantongjiFn();
          // this.getUserShopDatas();
        // this.getGonggao();
          // this.getTixianing();
         
        } else {
          // 这是管理员
          this.getpoxiao();
          this.initByAdmin();
        }
      },
      immediate: true,
      deep: true,
    },
   
  },
  async mounted() {
    // 加载默认布局
    this.loadLayoutFromStorage();
    this.$nextTick()

    await this.loadTheComponents();
    
    // 检查即将到期的业务
    this.checkExpireSoon();
    
    // // 初始化响应式布局
    // this.handleResponsiveLayout();
    
    // 监听窗口大小变化
    window.addEventListener('resize', this.onWindowResize);
  },
  methods: {
    goRenew() {
       this.$refs.expireSoonDialog.open(this.isExpressData);
    },
     // 获取商户端通知公告
  async getGonggao() {
      const homeNoticeId = localStorage.getItem("homeNoticeId");
      let res = await homeApi.notice()
    if(res.data.character.length > 0 &&
            (!homeNoticeId || homeNoticeId < res.data.character[0].noticeId)) {
      this.openNotice(res.data.character[0]);
      localStorage.setItem("homeNoticeId", res.data.character[0].noticeId);
    }
    },
       // 打开通知公告详情
    openNotice(item) {
      this.$refs.noticeDetailDialog.open(item);
    },
    
    // 检查即将到期的业务
    async checkExpireSoon() {
      try {
        const res = await homeApi.expireSoonIndex();
        if (res.data && res.data.length > 0) {
          this.isExpress = true;
          this.isExpressData = res.data;
          // 检查今天是否已经显示过弹窗
          if (this.shouldShowExpireDialog()) {
            this.$refs.expireSoonDialog.open(res.data);
          }
        }
      } catch (error) {
        
      }
    },
    
    // 检查今天是否应该显示过期弹窗
    shouldShowExpireDialog() {
      const today = new Date().toDateString(); // 获取今天的日期字符串
      const lastShownDate = localStorage.getItem('expireDialogLastShown');
      console.log(lastShownDate , today)
      return lastShownDate !== today;
    },
    
    // 设置今天已显示过期弹窗
    setExpireDialogShownToday() {
      const today = new Date().toDateString();
      localStorage.setItem('expireDialogLastShown', today);
    },
    
    // 过期弹窗关闭事件处理
    onExpireDialogClosed() {
      // 用户点击"我知道了"后，记录今天已显示过弹窗
      this.setExpireDialogShownToday();
    },
    async loadTheComponents() {
      // 批量获取所有需要的组件
      const componentNames = [
        'comp1', 'comp2', 'comp3', 'comp4', 'comp5',
        'comp6', 'comp7', 'comp8', 'comp9', 'comp10',
        'comp11', 'comp12','comp13'
      ];

      // 使用 ComponentLoader 批量加载组件
      const asyncComponents = ComponentLoader.getComponents(componentNames);

      // 动态注册组件
      Object.keys(asyncComponents).forEach(name => {
        this.$options.components[name] = asyncComponents[name];
      });

      // 或者使用 nextTick 确保更新完成
      this.isMounted = true
      await this.$nextTick();
      
                // 组件加载完成后立即计算一次高度
      // this.$nextTick(() => {
      //   this.calculateActualHeight();
      // });
      
      // 延迟再次计算，确保DOM完全渲染
      // setTimeout(() => {
      //   this.calculateActualHeight();
      // }, 500);
      
      
      // this.startHeightMonitoring();
  },
    containerResizedEvent(newLayout) {
    },
    // 从localStorage加载布局
    loadLayoutFromStorage() {
      try {
        const savedLayout = localStorage.getItem(this.layoutStorageKey);
        if (savedLayout) {
          this.layout = JSON.parse(savedLayout);
        } else {
          // 没有缓存时使用默认布局
          this.layout = _.cloneDeep(defaultLayout);
        }
        
        // 初始加载时不显示按钮，等待高度计算完成
        this.actualTotalHeight = 0;
      } catch (error) {
       
        this.layout = _.cloneDeep(defaultLayout);
        this.actualTotalHeight = 0;
      }
    },

    // 保存布局到localStorage
    saveLayoutToStorage() {
      try {
        localStorage.setItem(this.layoutStorageKey, JSON.stringify(this.layout));
     
      } catch (error) {
      
      }
    },

    // 布局更新时的回调
    onLayoutUpdated(newLayout) {
     
      this.layout = newLayout;
      
      // 延迟保存，避免拖拽过程中频繁保存
      this.debounceLayoutSave();
      
      // 延迟计算实际高度，等待DOM更新完成
      // this.$nextTick(() => {
      //   this.calculateActualHeight();
      // });
    },

    // 防抖保存布局
    debounceLayoutSave() {
      if (this.saveTimer) {
        clearTimeout(this.saveTimer);
      }
      this.saveTimer = setTimeout(() => {
        this.saveLayoutToStorage();
      }, 500); // 500ms后保存
    },

    // 重置布局为默认值
    resetLayout() {
      let that = this
       this.$confirm("确认重置页面布局吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
           that.layout = _.cloneDeep(defaultLayout);
      that.saveLayoutToStorage();
      that.$message.success('布局已重置为默认设置');
        })
        .catch(() => {});
     
   
      // 重新计算高度
        // this.calculateActualHeight();
    },



    // 计算实际组件高度
    calculateActualHeight() {
      console.log(this.actualTotalHeight,'actualTotalHeight')
      if (!this.layout || this.layout.length === 0) {
        // 如果没有布局数据，重置高度为0，不显示按钮
        this.actualTotalHeight = 0;
        return;
      }
      
      // 首先尝试使用配置高度作为基础
      const configHeight = this.gridTotalHeight;
      if (configHeight > 0) {
        this.actualTotalHeight = configHeight;
      }
      
      // 然后尝试计算实际DOM高度
      this.$nextTick(() => {
        let maxBottom = 0;
        
        // 遍历所有网格项，计算实际底部位置
        this.layout.forEach((item, index) => {
          const gridItem = this.$el.querySelector(`[data-grid-key="${item.i}"]`);
          if (gridItem) {
            const rect = gridItem.getBoundingClientRect();
            const containerRect = this.$el.querySelector('.vue-grid-layout');
            if (containerRect) {
              const containerRectBounds = containerRect.getBoundingClientRect();
              const relativeBottom = rect.bottom - containerRectBounds.top;
              maxBottom = Math.max(maxBottom, relativeBottom);
            }
          }
        });
        
        // 如果找到了实际高度，更新总高度
        if (maxBottom > 0) {
          const newHeight = maxBottom + 15; // 加上底部边距
          // 确保高度是合理的值（大于100px）
          if (newHeight > 100) {
            this.actualTotalHeight = newHeight;
            console.log('实际计算的总高度:', this.actualTotalHeight);
          } else {
            this.actualTotalHeight = 0;
            console.log('计算的高度过小，重置为0:', newHeight);
          }
        } else {
          // 如果无法计算实际高度，使用配置高度作为备选
          if (configHeight > 100) {
            this.actualTotalHeight = configHeight;
            console.log('使用配置高度作为备选:', this.actualTotalHeight);
          } else {
            // 如果连配置高度都没有或太小，重置为0
            this.actualTotalHeight = 0;
            console.log('无法计算有效高度，重置为0');
          }
        }
      });
    },

    // 获取组件实际高度
    getComponentHeight(componentId) {
      const component = this.$refs[componentId];
      if (component && component.$el) {
        return component.$el.offsetHeight;
      }
      return 0;
    },



   
    // 启动高度监控
    startHeightMonitoring() {
      // 每5秒检查一次高度变化
      //  this.heightMonitorTimer = setInterval(() => {
      // this.calculateActualHeight();
      // }, 5000);
    },

    // 停止高度监控
    stopHeightMonitoring() {
      if (this.heightMonitorTimer) {
        clearInterval(this.heightMonitorTimer);
        this.heightMonitorTimer = null;
      }
    },


    //admin 区分
       // 管理端的方法
    // 管理端统计初始化
    initByAdmin() {
      this.getGoodsTableDataTotal();
      this.getGoodsTableDataTimer();
      this.getYudouList();
      this.getSupplerUserTotal();
      this.getModuleYudouList();
      this.getServiceCount();
    },
    getServiceCount() {
      getServiceCount().then(res => { 
        this.serverList = res.data;
      });
    },
    // 获取商家注册用户统计
    getSupplerUserTotal() {
      getSupplerUserTotal().then((res) => {
        this.supplerUserTotal = res.data;
      });
    },    // 获取商家虞豆统计
    getYudouList() {
      // sortColumn  sort
      yudouCountByTenant(this.yudouParams).then((res) => {
        this.yudouList = res.data;
      });
    },
        // 获取账号统计表格 时间段
    getGoodsTableDataTimer() {
      // day:1昨天
      goodsCountByTenant(this.zuoriShangjiaCanshu).then((res) => {
        this.supplerGoodsYesterday = res.data;
      });
    },
       // 商品统计表格 总商品
    getGoodsTableDataTotal() {
      goodsCountByTenant(this.shangpintongjiCanshu).then((res) => {
        this.supplerGoodsTotal = res.data;
      });
    },
      getErpVer() {
      const localVer = localStorage.getItem("erp_ver");
      this.getDicts("ver").then((r) => {
        if (r.data && r.data.length) {
          const obj = this.arrayToObject(r.data, "dictLabel");
          localStorage.setItem("erp_ver", obj.erp_ver.dictValue);
          if (!localVer || Number(localVer) < Number(obj.erp_ver.dictValue)) {
            // 本地没有版本号或者本地版本小于服务端时 重新加载页面
            location.reload(true); // 强制从服务器重新加载
            console.log("%c Line:847 🥕 强制从服务器重新加载", "color:#e41a6a");
          }
        } else {
          localStorage.setItem("erp_ver", 1);
          if (!localVer) {
            // 本地没有版本号或者本地版本小于服务端时 重新加载页面
            location.reload(true); // 强制从服务器重新加载
            console.log("%c Line:847 🥕 强制从服务器重新加载", "color:#e41a6a");
          }
        }
      });
    },

        // 获取破晓余额
    getpoxiao() {
      checkPhoneApi.pxyue().then((res) => {
        this.poxiaoyue = res.data.data;
      });
    },
       // 虞豆类型统计排序
    yudouTypeTableChange(val) {
      this.yudouTypeParams.sort = val.order == "ascending" ? "asc" : "desc";
      this.yudouTypeParams.sortColumn = val.prop;
      this.getModuleYudouList();
    },
    // 获取模块虞豆消费统计
    getModuleYudouList() {
      getModuleYudou(this.yudouTypeParams).then((res) => {
        this.moduleYudouList = res.data;
      });
    },
      // 虞豆统计排序
    yudouSortChange(val) {
      this.yudouParams.sort = val.order == "ascending" ? "asc" : "desc";
      this.yudouParams.sortColumn = val.prop;
      this.getYudouList();
    },

     // 商品统计排序
     goodsTableChange(val) {
      this.shangpintongjiCanshu.sort = val.order == "ascending" ? "asc" : "desc";
      this.shangpintongjiCanshu.sortColumn = val.prop;
      this.getGoodsTableDataTotal();
    },
     // 昨日上架 排序
     goodsYestodayTableChange(val) {
      this.zuoriShangjiaCanshu.sort = val.order == "ascending" ? "asc" : "desc";
      this.zuoriShangjiaCanshu.sortColumn = val.prop;
      this.getGoodsTableDataTimer();
    },
  },

  beforeDestroy() {
    // 组件销毁前清除定时器
    if (this.saveTimer) {
      clearTimeout(this.saveTimer);
    }
    
    // 移除窗口大小变化监听
    window.removeEventListener('resize', this.onWindowResize);
    
    // 停止高度监控
    this.stopHeightMonitoring();
  },


}
</script>

<style scoped lang="scss">
.dashboard-container {
  width: 100%;
  background: #f3f3f3;
}

.dashboard-toolbar {
    display: flex;
    margin: 0 auto;
    align-items: center;
    justify-content: center;
    width: 288px;
    font-weight: 400;
    font-size: 14px;
    height: 64px;
    border-radius: 32px;
    border: 1px solid #666;
    cursor: pointer;
    
    .el-button {
      margin: 0 10px;
    }
}

/* 网格信息样式 */
.grid-info {
  .info-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 5px 0;
    
    .label {
      font-weight: bold;
      color: #606266;
    }
    
    .value {
      color: #409EFF;
      font-weight: bold;
    }
  }
}

/* 高度计算中提示样式 */
.height-calculating {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  color: #909399;
  font-size: 14px;
  
  .el-icon {
    margin-right: 8px;
    font-size: 16px;
  }
}

.vue-grid-layout {
  background: #f3f3f3;
  padding: 0;
  /* margin:-15px; */
}

.vue-resizable:not(.vue-grid-placeholder) {
  background: #fff;
  border-radius: 10px;
  padding: 14px 16px;
  position: relative;

}


.vue-grid-item .static {
  background: #cce;
}


.vue-grid-item .no-drag {
  height: 100%;
  width: 100%;
}

.vue-grid-item .minMax {
  font-size: 12px;
}

.vue-grid-item .add {
  cursor: pointer;
}

/* 自定义拖拽手柄样式 */
.grid-item .drag-handle {
  position: absolute;
  top: 5px;
  left: 50%;
  width: 30px;
  height: 20px;
  cursor: move;
  z-index: 10;
  display: flex;
  opacity: 0;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  background: rgba(108, 93, 211, 0.1);
  transition: all 0.2s ease;

}

@keyframes colorChange {
  0% {
    outline-color: transparent;
  }
  80% {
    outline-color: #907ff5;
  }
  100% {
    outline-color: #6c5dd3;
  }
}

.vue-resizable:hover {
  .drag-handle {
    opacity: 1;
  }
  .grid-item .vue-resizable-handle {
    display: block !important;
  }

  animation: colorChange 1s forwards; /* 引用动画名称 */
}

.drag-handle:hover {
  background: rgba(108, 93, 211, 0.2);
}

.drag-icon {
  font-size: 12px;
  color: #6C5DD3;
  font-weight: bold;
  line-height: 1;
  transform: rotate(90deg);
}

.vue-resizable-handle {
  opacity: 0;
}

.grid-item {

  outline: 1px solid transparent;
  box-sizing: border-box;

}


</style>
<style>
.vue-grid-item.vue-grid-placeholder {
  background: rgba(108, 93, 211, 0.8);
  transition-duration: 100ms;
  z-index: 2;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -o-user-select: none;
  user-select: none;
  border-radius: 10px;
}

.grid-item .vue-resizable-handle {
  display: none;
  width: 20px;
  height: 20px;
  background: url('../assets/img/index/move.png') no-repeat;
  background-size: 100% 100%;
}

.grid-item:hover .vue-resizable-handle {
  display: block;
}

.renrow-box {
    padding: 6px;
  background: #FFF4E3;
  border-radius: 4px 0px 4px 4px;
  align-items: center;
}
.renrow-box img {
  width: 17px;

}
.renrow-box span {
  text-decoration: underline;
  font-size: 14px;
  color: #F38642;
  margin-left: 2px;
  cursor: pointer;
}
</style>
